package com.yanqu.road.server.gameplayer.module.player;

import com.yanqu.road.entity.config.badge.BadgeConfig;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.enums.eBadgeType;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.log.LogBadgeUpgrade;
import com.yanqu.road.entity.player.UserBadge;
import com.yanqu.road.logic.bussiness.player.UserBadgeBussiness;
import com.yanqu.road.logic.pb.BadgePb;
import com.yanqu.road.pb.badge.BadgeProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.activity.curio.CurioModule;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.cricket.CricketModule;
import com.yanqu.road.server.gameplayer.module.drugstore.DrugStoreModule;
import com.yanqu.road.server.gameplayer.module.manor.ManorModule;
import com.yanqu.road.server.gameplayer.module.winery.WineryModule;
import com.yanqu.road.server.gameplayer.module.wingroom.WingRoomModule;
import com.yanqu.road.server.manger.config.BadgeConfigMgr;
import com.yanqu.road.server.manger.config.GoodsMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.player.BadgeMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.UUIDHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class BadgeModule extends GeneralModule {

    /**
     * 徽章类型、徽章id、徽章信息
     */
    private Map<Integer, List<UserBadge>> userBadgeMap = new ConcurrentHashMap<>();

    public BadgeModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        userBadgeMap = UserBadgeBussiness.getUserBadgeMap((player.getUserId()));
        return true;
    }

    public Map<Integer, List<UserBadge>> getUserBadgeMap() {
        return userBadgeMap;
    }


    @Override

    public boolean afterLoadData() {
        return false;
    }

    @Override
    public boolean saveData() {
        for (List<UserBadge> badgeList : userBadgeMap.values()) {
            for (UserBadge userBadge : badgeList) {
                if (userBadge.isInsertOption()) {
                    UserBadgeBussiness.addUserBadge(userBadge);
                } else if (userBadge.isUpdateOption()) {
                    UserBadgeBussiness.updateUserBadge(userBadge);
                }
            }
        }
        return true;
    }

    @Override
    public void afterLogin() {
        if (SystemOpenMgr.systemOpen(player, eSystemId.BadgeShow.getValue())) {
            initSystem();
            // 同步数据
            syncBadgeData();
        }
    }

    public void initSystem() {
        // 加载所有勋章
        for (eBadgeType badgeType : eBadgeType.values()) {
            if (badgeType.getValue() == eBadgeType.FishPond.getValue() && !userBadgeMap.containsKey(eBadgeType.FishPond.getValue())) {
                if (SystemOpenMgr.systemOpen(player, eSystemId.FishPond.getValue())) {
                    // 加载鱼塘徽章
                    player.getModule(ManorModule.class).getManorFishPondModel().updateBadge();
                }
            }else if (badgeType.getValue() == eBadgeType.WingRoom.getValue() && !userBadgeMap.containsKey(eBadgeType.WingRoom.getValue())) {
                if (SystemOpenMgr.systemOpen(player, eSystemId.WingRoom.getValue())) {
                    // 加载厢房徽章
                    player.getModule(WingRoomModule.class).updateBadge();
                }
            }else if (badgeType.getValue() == eBadgeType.DrugStore.getValue() && !userBadgeMap.containsKey(eBadgeType.DrugStore.getValue())) {
                if (SystemOpenMgr.systemOpen(player, eSystemId.DrugStore.getValue())) {
                    // 加载药铺徽章
                    player.getModule(DrugStoreModule.class).updateBadge();
                }
            }else if (badgeType.getValue() == eBadgeType.CurioScore.getValue() && !userBadgeMap.containsKey(eBadgeType.CurioScore.getValue())) {
                if (SystemOpenMgr.systemOpen(player, eSystemId.Curio.getValue())) {
                    // 加载藏品徽章
                    player.getModule(CurioModule.class).updateBadge();
                }
            } else if (badgeType.getValue() == eBadgeType.Winery.getValue() && !userBadgeMap.containsKey(eBadgeType.Winery.getValue())) {
                if (SystemOpenMgr.systemOpen(player, eSystemId.Winery.getValue())) {
                    // 加载酒坊徽章
                    player.getModule(WineryModule.class).updateBadge();
                }
            } else if (badgeType.getValue() == eBadgeType.Cricket.getValue() && !userBadgeMap.containsKey(eBadgeType.Cricket.getValue())) {
                if (SystemOpenMgr.systemOpen(player, eSystemId.Cricket.getValue())) {
                    // 加载蛐蛐徽章
                    player.getModule(CricketModule.class).updateBadge();
                }
            }
        }
    }

    /**
     * 同步勋章数据
     */
    public void syncBadgeData() {
        BadgeProto.BadgeDataMsg.Builder msg = BadgePb.parseBadgeDataMsg(userBadgeMap);
        if (null != msg) {
            player.sendPacket(Protocol.U_BADGE_DATA, msg);
        }
    }

    /**
     * 设置财神送礼展示,只能有一个展示
     *
     * @param badgeId   徽章id
     * @param badgeType 徽章类型
     */
    public int setDisperseGoldShow(int badgeId, int badgeType, boolean disperseGoldShow) {
        synchronized (userBadgeMap) {
            if (!userBadgeMap.containsKey(badgeType)) {
                // 徽章不存在
                return GameErrorCode.E_BADGE_NOT_EXIST;
            }
            List<UserBadge> badgeList = userBadgeMap.get(badgeType);
            UserBadge userBadge = null;
            for (UserBadge badge : badgeList) {
                if (badge.getBadgeId() == badgeId) {
                    userBadge = badge;
                    break;
                }
            }
            if (userBadge == null) {
                // 徽章不存在
                return GameErrorCode.E_BADGE_NOT_EXIST;
            }
            // 已经是展示状态
            if (disperseGoldShow && userBadge.isDisperseGoldShow()) {
                return GameErrorCode.E_BADGE_IS_DISPERSE_GOLD_SHOW;
            }
            // 已经不是展示状态
            if (!disperseGoldShow && !userBadge.isDisperseGoldShow()) {
                return GameErrorCode.E_BADGE_IS_NOT_DISPERSE_GOLD_SHOW;
            }
            if (disperseGoldShow) {
                // 先取消原先的展示
                UserBadge showBadge = getDisperseGoldShowBadge();
                if (showBadge != null) {
                    showBadge.setDisperseGoldShow(false);
                }
            }
            userBadge.setDisperseGoldShow(disperseGoldShow);
        }
        updateUserBadgeMap();
        syncBadgeData();
        return 0;
    }

    /**
     * 添加勋章
     */
    public void addBadge(int badgeId, int badgeType) {
        int replaceIdx = -1;
        synchronized (userBadgeMap) {

            UserBadge needUpdateBadge = getNeedUpdateBadge(badgeId, badgeType);

            // 【替换成新勋章】
            if (needUpdateBadge != null) {
                int oldBadgeId = needUpdateBadge.getBadgeId();
                // 如果徽章已佩戴，需要升级到新的徽章
                List<String> badgeList = StringUtils.stringToStringList(player.getUserInfo().getBadge(), "\\|");
                replaceIdx = badgeList.indexOf(oldBadgeId + "," + needUpdateBadge.getBadgeType());
                // 更新徽章
                needUpdateBadge.setBadgeId(badgeId);
                // 升级日志
                AutoLogMgr.add(new LogBadgeUpgrade(player.getUserId(), badgeType, oldBadgeId, badgeId, new Date()));
            } else {
                // 【新增一个勋章】
                UserBadge userBadge = initUserBadge(player.getUserId(), badgeId, badgeType);
                // 获得第一个徽章时，默认勾选该徽章进行送财展示
                userBadge.setDisperseGoldShow(userBadgeMap.values().stream().mapToInt(List::size).sum() == 0);
                // 添加进map
                List<UserBadge> list = userBadgeMap.getOrDefault(badgeType, new ArrayList<>());
                list.add(userBadge);
                userBadgeMap.put(badgeType, list);
                // 解锁日志
                AutoLogMgr.add(new LogBadgeUpgrade(player.getUserId(), badgeType, 0, badgeId, new Date()));
            }
        }

        if (replaceIdx != -1) {
            // 替换徽章
            player.getModule(PlayerModule.class).replaceBadge(badgeId, badgeType, replaceIdx);
        }

        updateUserBadgeMap();
        syncBadgeData();
    }

    /**
     * 初始化勋章
     *
     * @param userId      用户id
     * @param badgeId     勋章id
     * @param badgeType   勋章类型
     */
    public UserBadge initUserBadge(long userId, int badgeId, int badgeType) {
        UserBadge userBadge = new UserBadge();
        userBadge.setUid(UUIDHelper.randomUUID(String.valueOf(GameServer.getInstance().getServerId())));
        userBadge.setUserId(userId);
        userBadge.setBadgeId(badgeId);
        userBadge.setBadgeType(badgeType);
        userBadge.setDisperseGoldShow(false);
        userBadge.setInsertOption();
        return userBadge;
    }

    /**
     * 是否只能拥有一个徽章
     */
    private boolean isSingleBadge(int badgeType) {
        return badgeType == eBadgeType.FishPond.getValue()
                || badgeType == eBadgeType.WingRoom.getValue()
                || badgeType == eBadgeType.DrugStore.getValue()
                || badgeType == eBadgeType.Winery.getValue()
                || badgeType == eBadgeType.Cricket.getValue()
                || badgeType == eBadgeType.CricketCourt.getValue()
                || badgeType == eBadgeType.CurioScore.getValue()
                || badgeType == eBadgeType.MusicRoom.getValue();
    }

    /**
     * 获取要更新的勋章
     *
     * @return null表示需要新增
     */
    private UserBadge getNeedUpdateBadge(int badgeId, int badgeType) {
        List<UserBadge> list = getUserBadgeMap().getOrDefault(badgeType, new ArrayList<>());

        // 只能有一个
        if (isSingleBadge(badgeType)) {
            return list.isEmpty() ? null : list.get(0);
        }

        // 拿配置（鱼塘勋章不在这里面）
        BadgeConfig config = BadgeConfigMgr.getBadgeConfig(badgeType, badgeId);

        // 瓦舍勋章
        if (badgeType == eBadgeType.Washe.getValue()) {
            List<Integer> paramList = config.getSeasonParamList();
            int season = paramList.get(0);
            int smallType = paramList.get(1);
            for (UserBadge tmpBadge : list) {
                BadgeConfig tmpConfig = BadgeConfigMgr.getBadgeConfig(badgeType, tmpBadge.getBadgeId());
                List<Integer> tmpParamList = tmpConfig.getSeasonParamList();
                if (tmpParamList.get(0) == season && tmpParamList.get(1) == smallType) {
                    return tmpBadge;
                }
            }
        }
        return null;
    }

    /**
     * 获取财神展示的徽章
     */
    public UserBadge getDisperseGoldShowBadge() {
        return userBadgeMap.values().stream()
                .flatMap(Collection::stream)
                .filter(UserBadge::isDisperseGoldShow)
                .findFirst()
                .orElse(null);
    }

    private void updateUserBadgeMap() {
        List<UserBadge> userBadgeList = new ArrayList<>();
        userBadgeMap.values().forEach(userBadgeList::addAll);
        BadgeMgr.updateUserBadge(player.getUserId(), userBadgeList);
    }

    /**
     * 使用道具获得勋章
     */
    public void addBadgeByItem(int itemId) {
        log.info("userId {} use item {} add badge", getUserId(), itemId);

        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(itemId);
        if (goodsInfo == null) {
            log.error("userId {} add badge error! itemId {}, no goodsInfo.", getUserId(), itemId);
            return;
        }

        int badgeType = goodsInfo.getParamList().get(0).intValue();
        int badgeId = goodsInfo.getParamList().get(1).intValue();
        BadgeConfig badgeConfig = BadgeConfigMgr.getBadgeConfig(badgeType, badgeId);
        if (badgeConfig == null) {
            log.error("userId {} add badge error! itemId {} badgeType {} badgeId {}, no badge config.", getUserId(), itemId, badgeType, badgeId);
            return;
        }

        addBadge(badgeId, badgeType);
    }
}
